package com.koron.common.core.business.print;

import cn.hutool.core.lang.Assert;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.internal.LinkedTreeMap;
import com.koron.bean.util.RedisUtils;
import com.koron.common.core.business.print.bean.PrintTemplateBean;
import com.koron.common.core.business.print.bean.ReportFieldBean;
import com.koron.common.core.business.print.bean.ReportTaskBean;
import com.koron.common.core.business.print.printstandard.ReportServiceStandardImpl;
import com.koron.common.core.util.FastJsonUtils;
import com.koron.print.FieldBean;
import com.koron.print.PrintInterface;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 打印服务接口实现
 *
 * @author fhq
 */
@Slf4j
public class PrintImpl implements PrintInterface {

    @Override
    public ArrayList<FieldBean> getFieldList(String strTaskId) {

        ReportTaskBean bean = getReportTaskBean(strTaskId);//获取打印相关

        String fields = bean.getReportServiceInterface().getField();
        List<ReportFieldBean> list = FastJsonUtils.getJsonToList(fields, ReportFieldBean.class);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }

        ArrayList<FieldBean> desList = new ArrayList<>();
        FieldBean fieldBean = null;
        for (ReportFieldBean item : list) {
            fieldBean = new FieldBean(item.getFieldCode(), item.getFieldName(), item.getFieldType());
            desList.add(fieldBean);
        }
        return desList;
    }

    /**
     * 获取打印相关
     * 优先从本地缓存拿，取不到会去从redis上拿
     *
     * @param strTaskId
     * @return
     */
    private ReportTaskBean getReportTaskBean(String strTaskId) {
        strTaskId = "Print-" + strTaskId;
        ReportTaskBean bean = ReportTask.printTaskTimedCache.get(strTaskId);
        //找不到 redis的ping方法 暂时写true
        if (bean == null && true) {
            log.info("取redis打印信息,taskId:{}",strTaskId);
            String taskBeanJson = RedisUtils.get(strTaskId).toString();
            bean = stringToBean(taskBeanJson);
        }
        Assert.notNull(bean, "没有查询到打印数据，请重试！");
        return bean;
    }


    @Override
    public byte[] getFileBytes(String strTaskId) {
        ReportTaskBean bean = getReportTaskBean(strTaskId);//获取打印相关

        byte[] content = bean.getReportServiceInterface().getTemplateListById().getContent();
        if (StringUtils.isEmpty(content)) {
            return null;
        }

        //如果是打印任务，取完格式文件后，将任务清除
        if (bean.getTaskType().equals(ReportTaskBean.TASKTYPE_PRINT)) {
            ReportTask.printTaskTimedCache.remove(strTaskId);//本地缓存请设置过期
            //找不到 redis的ping方法 暂时写true
            if (true) {
                RedisUtils.expire(strTaskId, 1);//redis缓存请设置过期
            }
        }
        return content;
    }

    @Override
    public String getFilePath(String arg0) {
        return null;
    }

    @Override
    public ArrayList<HashMap<String, String>> getPrintData(String strTaskId) {
        ReportTaskBean bean = getReportTaskBean(strTaskId);//获取打印相关

        ArrayList<HashMap<String, String>> data = bean.getPrintData();
        return data;
    }

    @Override
    public void writeFileBytes(String strTaskId, byte[] contentBytes) {
        ReportTaskBean bean = getReportTaskBean(strTaskId);//获取打印相关

        //打印模版设计，如果有保存动作，刚重置时间。
        bean.setTimeStamp(new Date().getTime());
        ReportTask.printTaskTimedCache.put(strTaskId, bean);
        RedisUtils.expire(strTaskId, 1440 * 60);
        PrintTemplateBean printTemplateBean = bean.getReportServiceInterface().getPrintTemplate();
        printTemplateBean.setContent(contentBytes);
        bean.getReportServiceInterface().updateTemplateContent();
    }

    /**
     * 转换对象
     *
     * @author dulingjiang
     * @date 2020年8月10日
     */
    @SuppressWarnings("rawtypes")
    private ReportTaskBean stringToBean(String data) {
        ReportTaskBean bean = new ReportTaskBean();
        Gson gson = new Gson();
        HashMap map = gson.fromJson(data, HashMap.class);
        ReportServiceInterface impl = null;
        //1.printData对象
        String mapdata = gson.toJson(map.get("printData"));
        ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
        try {
            JsonArray arry = new JsonParser().parse(mapdata).getAsJsonArray();
            for (JsonElement jsonElement : arry) {
                HashMap<String, String> one = setNullValue(gson.fromJson(jsonElement, HashMap.class));
                list.add(one);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        bean.setPrintData(list);

        //2.reportServiceInterface对象
        LinkedTreeMap<String, Object> mapSon = (LinkedTreeMap) map.get("reportServiceInterface");
        if ("print".equals(mapSon.get("mark"))) {
            String json = gson.toJson(mapSon.get("printTemplate"));
            log.info(json);
//            PrintTemplateBean printTemplateBean = gson.fromJson(json, PrintTemplateBean.class);
            PrintTemplateBean printTemplateBean = FastJsonUtils.getJsonToBean(json, PrintTemplateBean.class);
            impl = new ReportServiceStandardImpl(printTemplateBean);
        }
        bean.setReportServiceInterface(impl);
        return bean;
    }

    public static <T> T setNullValue(T source) throws IllegalArgumentException, IllegalAccessException, SecurityException {
        Field[] fields = source.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.getGenericType().toString().equals(
                    "class java.lang.String")) {
                field.setAccessible(true);
                Object obj = field.get(source);
                if (obj != null && obj.equals("")) {
                    field.set(source, null);
                } else if (obj != null) {
                    String str = obj.toString();
                    str = StringEscapeUtils.escapeSql(str);//StringEscapeUtils是commons-lang中的通用类
                    field.set(source, str.replace("\\", "\\" + "\\").replace("(", "\\(").replace(")", "\\)")
                            .replace("%", "\\%").replace("*", "\\*").replace("[", "\\[").replace("]", "\\]")
                            .replace("|", "\\|").replace(".", "\\.").replace("$", "\\$").replace("+", "\\+").trim()
                    );
                }
            }
        }
        return source;
    }
}
